package cn.onein.edu.web.dao;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.orm.ibatis.SqlMapClientCallback;
import org.springframework.orm.ibatis.SqlMapClientTemplate;
import org.springframework.stereotype.Service;

import cn.onein.edu.biz.bean.ActionCategory;
import cn.onein.edu.biz.bean.DailyAction;
import cn.onein.edu.biz.bean.Product;
import cn.onein.edu.biz.bean.User;
import cn.onein.edu.biz.bean.UserAction;
import cn.onein.edu.biz.bean.UserTemp;
import cn.onein.edu.common.ActionResultType;
import cn.onein.edu.common.ProductType;
import cn.onein.edu.util.DateUtil;

import com.ibatis.sqlmap.client.SqlMapExecutor;

@Service
public class UserDao {

	private final static Integer YESTERDAY = -1;

	private final static Integer NEXTWEEKDAY = 6;

	private final static Integer TOMORROWDAY = 1;

	@Autowired
	private SqlMapClientTemplate sqlMapClientTemplate;

	public ActionCategory getCategoryByAge(Integer age) {
		return (ActionCategory) sqlMapClientTemplate.queryForObject(
				"getCategoryByAge", age);
	}

	public ActionCategory getCategoryByAgeAndSex(Map<String, Object> map) {
		return (ActionCategory) sqlMapClientTemplate.queryForObject(
				"getCategoryByAgeAndSex", map);
	}

	public void saveRegisterUser(User user) {
		sqlMapClientTemplate.insert("insertRegisterUser", user);
	}

	public User getUserByEmail(String email) {
		return (User) sqlMapClientTemplate.queryForObject("getUserByEmail",
				email);
	}

	@SuppressWarnings("unchecked")
	public List<Product> getProductByType(ProductType pType) {
		return (List<Product>) sqlMapClientTemplate.queryForList("getProductByType", pType.ordinal());
	}

	public User getUserByName(String name) {
		return (User) sqlMapClientTemplate
				.queryForObject("getUserByName", name);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void updateUser(final Map<String, Object> param,
			final UserTemp userTemp) {
		sqlMapClientTemplate.execute(new SqlMapClientCallback() {
			public Object doInSqlMapClient(SqlMapExecutor executor)
					throws SQLException {
				executor.startBatch();
				executor.update("updateUser", param);
				if (null != userTemp) {
					executor.insert("insertUserTemp", userTemp);
				}
				executor.executeBatch();
				return null;
			}
		});
	}

	public User getUserById(Long id) {
		return (User) sqlMapClientTemplate.queryForObject("getUserById", id);
	}

	public void updateUserPassword(Map<String, Object> param) {
		sqlMapClientTemplate.update("updateUserPassword", param);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void updateUserActionByBirthday(final User user,final User oldUser) {
		sqlMapClientTemplate.execute(new SqlMapClientCallback() {
			public Object doInSqlMapClient(SqlMapExecutor executor)
					throws SQLException {
				executor.startBatch();

				Date actionDate = new Date();
				Date endDate = DateUtil.getDateBydays(new Date(), NEXTWEEKDAY);

				while (!endDate.before(actionDate)) {
					Date birthday = user.getBirthday();
					Integer age = DateUtil.birthday2Age(birthday, actionDate);
					ActionCategory category = (ActionCategory) executor.queryForObject("getCategoryByAge", age);
					if (category != null) {
						// 取得Actionindex
						Integer actionIndex = DateUtil.calcActionIndexByBirthday(birthday, actionDate);

						DailyAction dailyAction = new DailyAction();
						dailyAction.setActionCatId(category.getId());
						dailyAction.setVersion(category.getCurrVersion());
						dailyAction.setActionIndex(actionIndex);

						// 取得要Insert的DailyAction
						dailyAction = (DailyAction) executor.queryForObject(
								"getDailyActionByCategory", dailyAction);
						if (dailyAction != null) {
							// 插入nextWeekDate的数据到UserActions表
							UserAction userAction = new UserAction();

							userAction.setUserId(oldUser.getId());
							userAction.setActionDate(actionDate);
							userAction.setDailyActionId(dailyAction.getId());

							executor.update("updateUserDailyActionId",userAction);
						}
					}

					actionDate = DateUtil.getDateBydays(actionDate, TOMORROWDAY);
				}

				executor.executeBatch();
				return null;
			}
		});

	}

	public void saveUserTemp(UserTemp userTemp) {
		sqlMapClientTemplate.insert("insertUserTemp", userTemp);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	public void insertInitUserActionForNewUser(final User user) {
		sqlMapClientTemplate.execute(new SqlMapClientCallback() {
			public Object doInSqlMapClient(SqlMapExecutor executor)
					throws SQLException {
				executor.startBatch();
				Date actionDate = DateUtil.getDateBydays(new Date(), YESTERDAY);
				Date endDate = DateUtil.getDateBydays(new Date(), NEXTWEEKDAY);

				while (!endDate.before(actionDate)) {
					Date birthday = user.getBirthday();
					Integer age = DateUtil.birthday2Age(birthday, actionDate);
					ActionCategory category = (ActionCategory) executor.queryForObject("getCategoryByAge", age);
					if (category != null) {
						// 取得Actionindex
						Integer actionIndex = DateUtil.calcActionIndexByBirthday(birthday, actionDate);

						DailyAction dailyAction = new DailyAction();
						dailyAction.setActionCatId(category.getId());
						dailyAction.setVersion(category.getCurrVersion());
						dailyAction.setActionIndex(actionIndex);

						// 取得要Insert的DailyAction
						dailyAction = (DailyAction) executor.queryForObject(
								"getDailyActionByCategory", dailyAction);
						if (dailyAction != null) {
							// 插入nextWeekDate的数据到UserActions表
							UserAction userAction = new UserAction();

							userAction.setActive(Boolean.FALSE);
							userAction.setUserId(user.getId());
							userAction.setActionDate(actionDate);
							userAction.setDailyActionId(dailyAction.getId());
							userAction.setActionResult(ActionResultType.NeverDone.ordinal());

							executor.insert("insertUserActions", userAction);
						}
					}

					actionDate = DateUtil.getDateBydays(actionDate, TOMORROWDAY);
				}

				executor.executeBatch();
				return null;
			}
		});
	}
	
	public void updateUserExtendInfo(User user){
		sqlMapClientTemplate.update("updateUserExtendInfo", user);
	}
	
	public UserTemp getUserTempByUUID(String uuid){
		return (UserTemp)sqlMapClientTemplate.queryForObject("getUserTempByUUID", uuid);
	}

	public void updateUserEmailByUserId(Map<String,Object> param){
		sqlMapClientTemplate.update("updateUserEmailByUserId", param);
	}
	
	public void deleteUserTempByUUID(String uuid){
		sqlMapClientTemplate.delete("deleteUserTempByUUID", uuid);
	}
	
	public void updateUserLevelExpries(Map<String,Object> param){
		sqlMapClientTemplate.update("updateUserLevelExpries", param);
	}
}
